# -*- coding: utf-8 -*-
import base64
import json
from collections import OrderedDict

import requests
from Crypto.Cipher import PKCS1_v1_5 as Cipher_pkcs1_v1_5
from Crypto.Hash import MD5
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5 as Signature_pkcs1_v1_5
from django.conf import settings

from async import async_job
from common.cache import redis_cache
from common.order import db as order_db
from common.order.model import PAY_STATUS
from common.utils import track_logging
from common.utils.exceptions import ParamError

_LOGGER = track_logging.getLogger(__name__)

APP_CONF = {
    '9010001093': {
        'API_KEY': '',
    }
}

_my_public_key = """-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm6A4TXa9UCEe6fBfVVsu
W1qUGPON4w9WLNRZQ6etcIZHgn6BV6PE5/WxoVXjRGafG5jsBspVzr1pHaqMUZ0B
66juV4z4ghKxolAEbGUgysDb/WDqJGvPKkHf7MeTGxfcVpzMRxiQ7dHpazVuzIHR
Eg5qcZGNGllhKya4FMSk4STUcQj75gv0eAUSuQfO5RlF1Q0QqtCFzUyVXSk97yjX
TqJvTe3MiX1jn/w+RMn9lkz9v3aCkj2PgelcmgBt+rlZpNZtX9ujnws4KIlVX/Iv
T81Pd+39t/aF4gzbFiZaJ8O02+6u4zBbrU+ziujlUOptY3eNnx3/QQE1JJiS5zmY
QQIDAQAB
-----END PUBLIC KEY-----"""

_my_private_key = """-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAjrYw/lcdKifJCcdFmCX083Dw4r10Jfp/PhRXrM3TPYLePhr8
Lwraw5ctS/nC5w+GYow8I+x337BKGcha7R8cUB5vCxTqZ6z7+E0ISVjPmDQDEKbs
ummqbspLASXN4gavulnqwNZ9UQMJXsPQATKUqLbN8SLRnvoEyRJMXJcfQWqHQ/KE
8HiIohD8qTwt01/VZUGNK2fys+nvaAZY+wzHX31eKrejCzYNy0oYvPQ4PPe/kdjx
OQhpmO6WnfuDgokFShQh44ZNXE4T2nWvzgxnfZX1tel+yOPYz+EntowaMGqHgv+3
8/2+sABwkL1Bgqc0QZ1K1G6WTvmAXwA6Lx2I2QIDAQABAoIBAAkMzLaUV6kgtMMF
/AfWAF6fvubiFMeDxyXsrFKtCsRP1EAj/fINwim9IIY85Hs6pM8DDZ1JlaB90XUp
G3sGCgmapHgTb3n7ok7ws6HTG/cO9VLNAx4fLUuxUGhWOWQoAGTU5uorr+6/Pozf
5gTtbDf2v8CW8KwgNsV5f5Yvjy/atUNkBDcqo9pCijBzMbwdHHzL8k6AtfvKDo4P
P297CRSjbVMeZXW33dTnoGSeVDi+/BGg+qWYLXljq6WdIbKEUeagOZYXcaWGq6xK
2Bnhpyxo/cZPFJ735jU2K7v1KMYsV2czX6yGt3fU5+sfOQa5j7Je5p3D9Rd2IdXH
Uw42tMECgYEAzUYM+5zJ5Q8yHFIXGOC8FvUmhI/kl9EWpvqq7ysA3RxhWU3V9Kr0
NjpSJJ4LiXnhmo2NCQm653Ci1ZAQllSPBUexY5ZmJ1STv0h7a0Q8ZJo2KNKdxCGK
wqjzFQCIEpQDffcovffA6qr/D84OD5AL6ACicTL1t9S67sgoIctmaM0CgYEAsfpe
SstAkA2sF5gbVofG8NSbNkkIYEaccJTqOlZsdze+hBcMBlSYWlouFGIBhDGEuU5l
RKtPSmBnCic/ex9QtC+XNiagCp7+A5JQugWjmJERzmjJdE5eb0bv/Gebwui3BGZ2
tQCGf9fkkM4SPC0WlykqltFcHJqRxNgQ9czQ0D0CgYAhc6D5//sG0Qshgl8xNq5w
L1MvlyNxeilu3Lqubxuc7NsQapbLYHCbxbVNMlQ++xXA0gCB0Iwc20Yt92Q8m1sT
STOnPwM2tZm+OlmiiWQuINNio7ACHlU2k8HJUmTaYjSPeo+xJYbStzsJoFK6Rocq
L7BJMjzI0GoGL6gamcL+oQKBgAchoxmYH1QmWBjx7VaARkZsHnQEZSOGcMpKDUCd
Ked1AltEmSS/ywMDzgjfDHSBj3HlZEVmH905E6fifrauQIuXxJVU4uDKEh+Og1GQ
3EdGuNHufPP+F+aZjxAsDp+2t26jtGn4RWtl+TCcMTrcC6Wu7pfwd6JlxyV+Ct/u
fwd5AoGAFKq/XWjvzZqPP36w4IJqhSZQ2RszhOzny9d77xaWSXAR99ytDiSqgAxG
mfuOLQbgMBNhLtu1uy/P9nvhkVHzc/Ut9rVpwtWyr5VQXMCWPHUoOJ+QRpaWFegE
l1FlspFEtFaXhOuhfZzhcVsv9lQC/tHJj7KM+BLC8HJYAUPc0lc=
-----END RSA PRIVATE KEY-----"""

_GATEWAY = 'http://www.johutech.com/johuPay/payment/toH5'
_QUERY_GATEWAY = 'http://www.johutech:8682/johuPosp/cashierDesk/orderQuery'


def rsa_long_encrypt(pub_key_str, msg, length=117):
    """
    单次加密串的长度最大为 (key_size/8)-11
    1024bit的证书用100， 2048bit的证书用 200
    """
    pubobj = RSA.importKey(pub_key_str)
    pubobj = Cipher_pkcs1_v1_5.new(pubobj)
    res = []
    for i in range(0, len(msg), length):
        res.append(pubobj.encrypt(msg[i:i + length]))
    return "".join(res)


def rsa_long_decrypt(priv_key_str, msg, length=128):
    """
    1024bit的证书用128，2048bit证书用256位
    """
    privobj = RSA.importKey(priv_key_str)
    privobj = Cipher_pkcs1_v1_5.new(privobj)
    res = []
    for i in range(0, len(msg), length):
        res.append(privobj.decrypt(msg[i:i + length], 'xyz'))
    return "".join(res)


def _gen_sign(message, the_key):
    key = RSA.importKey(the_key)
    h = MD5.new(message)
    signer = Signature_pkcs1_v1_5.new(key)
    signature = signer.sign(h)
    signature = base64.b64encode(signature)
    return signature


def _verify_sign(data, signature, key):
    key = RSA.importKey(key)
    h = MD5.new(data)
    verifier = Signature_pkcs1_v1_5.new(key)
    if verifier.verify(h, base64.b64decode(signature)):
        return True
    return False


def urlsafe_b64decode(rsp_context):
    rsp_context.replace('-', '+').replace('_', '/')
    mod4 = len(rsp_context) % 4
    if mod4 > 0:
        rsp_context += '===='[mod4:]
    return base64.b64decode(rsp_context)


# 支付方式 1：微信 3：QQ。不传默认微信
def _get_pay_type(service):
    if service == 'wxpay':
        payType = '1'
    elif service == 'alipay':
        payType = '2'
    elif service == 'qq':
        payType = '3'
    else:
        payType = '1'
    return payType


def _get_device_ip(info):
    try:
        extra = json.loads(info['extra'])
    except:
        extra = {}
    user_info = extra.get('user_info', {})
    return user_info.get('device_ip') or '58.64.187.24'


def generate_sign_str(parameter):
    s = ''
    for k in sorted(parameter.keys()):
        if k != 'sign':
            s += '%s=%s&' % (k, parameter[k])
    return s[:len(s) - 1]


def _build_form(params):
    html = u"<head><title>loading...</title></head><form id='submit' name='submit' action='" + _GATEWAY + "' method='post'>"
    for k, v in params.items():
        html += "<input type='hidden' name='%s' value='%s'/>" % (k, v)
    html += "</form>"
    html += "<script>document.forms['submit'].submit();</script>"
    return html


def create_charge(pay, pay_amount, info):
    ''' 创建订单 '''
    app_id = info['app_id']
    service = info.get('service')
    parameter_dict = OrderedDict((
        ('memberCode', app_id),
        ('orderNum', str(pay.id)),
        ('payMoney', str(pay_amount)),
        ('payType', _get_pay_type(service)),
        ('sceneInfo', 'charge'),
        ('ip', _get_device_ip(info)),
        ('callbackUrl', '{}/pay/api/{}/quick_money/{}'.format(settings.NOTIFY_PREFIX, settings.NOTIFY_PATH, app_id)),
    ))
    s = generate_sign_str(parameter_dict)
    parameter_dict['signStr'] = _gen_sign(s, _my_private_key)
    _LOGGER.info("quick_money create charge data: %s ,dict: %s", s, parameter_dict)
    html = _build_form(parameter_dict)
    cache_id = redis_cache.save_html(pay.id, html)
    return {'charge_info': settings.PAY_CACHE_URL + cache_id}


def verify_notify_sign(params, key):
    sign = params['signStr']
    params.pop('signStr')
    s = generate_sign_str(params).encode('utf8')
    if not _verify_sign(s, sign, key):
        _LOGGER.info("quick_money sign verify error :%s, sign", params, sign)
        raise ParamError('sign not pass, data: %s' % params)


# {
# "resCode ": "0000",
# }
def check_notify_sign(request, app_id):
    _LOGGER.info("quick_money notify body: %s", request.body)
    data = json.loads(request.body)
    verify_notify_sign(data, _my_public_key)
    pay_id = data['orderNum']
    if not pay_id:
        _LOGGER.error("fatal error, out_trade_no not exists, data: %s" % data)
        raise ParamError('quick_money event does not contain pay ID')

    pay = order_db.get_pay(int(pay_id))
    if not pay:
        raise ParamError('pay_id: %s invalid' % pay_id)
    if pay.status != PAY_STATUS.READY:
        raise ParamError('pay %s has been processed' % pay_id)

    mch_id = data['memberCode']
    trade_status = str(data['respType'])
    trade_no = data['orderNum']
    total_fee = data['payMoney']

    extend = {
        'trade_status': trade_status,
        'trade_no': trade_no,
        'total_fee': total_fee
    }

    from common.channel.pay import check_channel_order
    check_channel_order(pay_id, total_fee, app_id)

    # 1 处理中; 2 交易成功; 3交易失败;
    if trade_status == '2':
        _LOGGER.info('quick_money check order success, mch_id:%s pay_id:%s' % (mch_id, pay_id))
        order_db.add_pay_success(mch_id, pay_id, total_fee, trade_no, extend)
        async_job.notify_mch(pay_id)


def query_charge(pay_order, app_id):
    ''' 查询订单 '''
    pass
    # 第三方 暂无开放计划


def query_test():
    parameter_dict = OrderedDict((
        ('memberCode', '9010001093'),
        ('orderNum', '2132313'),
    ))
    s = generate_sign_str(parameter_dict)
    print s
    sign = _gen_sign(s, _my_private_key)
    print sign
    parameter_dict['signStr'] = sign
    headers = {'Content-Type': 'application/x-www-form-urlencoded'}
    response = requests.post(_QUERY_GATEWAY, data=parameter_dict, headers=headers, timeout=3)
    print response.text


sss = '''{"interfaceType":"2","memberCode":"9010001093","orderNum":"1627887601139580928","payMoney":"10.00","payNum":"20180116154114790225","payTime":"20180116154137","payType":"1","platformType":"3","respType":"2","resultCode":"0000","resultMsg":"交易成功","signStr":"V20bLiipBN5kHVBMI+9/ejeWk+5LCMrMQ/705K9tgseAZyoSZccE6QtGvtFMV6NAEPfB0f/thXOQgPkLH/cQyDPuij+mv45l/wAJ70EpsY6BRFpBGH5MCNwR1YPpZxaob6I1lxx5Whcqp0vn8pmA4HZb2+OyO/7FDF2ohb2TStZKllIRCIJDAAesfqTfSBvbv8TTuam7761UeZ5NW8eb7Vl0XKGQlQwS36EHZo8387vSOnDM1/iIq5Vzd4La6Vs91HJAqKCfBLTY8EZr8+lYBCLsvJ72n2s263Ogl4+BjRhCNdtugdtTs4cZT+nJYv/VEPvaazKjlOu8wPXqIuOW3w=="}'''
if __name__ == '__main__':
    print type(sss)
    # request_body = sss.decode('unicode_escape').encode('utf-8')
    data = json.loads(sss)
    print type(data)
    print data
    print verify_notify_sign(data, _my_public_key)
